/*
 * Created by Jaren at 2021/11/29 8:56
 */
import 'dart:typed_data';

import 'package:inmotion_protocol/common/compact.dart';
import 'package:inmotion_protocol/common/exceptions.dart';
import 'package:inmotion_protocol/common/vehicle_info.dart';
import 'package:inmotion_protocol/lorin/bean/common/date.dart';
import 'package:inmotion_protocol/lorin/constant.dart';
import 'package:inmotion_protocol/lorin/factory/special/special_message_factory.dart';
import 'package:inmotion_protocol/lorin/lorin_message.dart';
import 'package:inmotion_protocol/util/byte_util.dart';

abstract class EucLorinSpecialMessageFactory<T extends EucCmdCompact>
    extends SpecialMessageFactory<T> {
  EucLorinSpecialMessageFactory(ProductProperty productProperty)
      : super(productProperty);

  LorinMessage genGetFwVersionMsg(
    int? source,
    int? target,
  ) {
    return genSpecialOne2OneReadMsg(
        compact!.fwVersion(), null, null, false, source, target);
  }

  LorinMessage genRequestVehicleSynthesizeRealTimeInfo() {
    return genSpecialOne2OneReadMsg(compact!.deviceRealTimeInfoCmd());
  }

  LorinMessage genRequestTBoxEsimList() {
    return genSpecialOne2OneReadMsg(compact!.tBoxEsimListCmd(), null, null,
        false, null, Constant.deviceTBox);
  }

  LorinMessage genRequestTBoxRealTimeInfo() {
    return genSpecialOne2OneReadMsg(compact!.tBoxRealTimeInfoCmd(), null, null,
        false, null, Constant.deviceTBox);
  }

  LorinMessage genTBoxInfo() {
    return genSpecialOne2OneReadMsg(
        compact!.tBoxCmd(), null, null, false, null, Constant.deviceTBox);
  }

  LorinMessage genTBoxDeviceId() {
    return genSpecialOne2OneReadMsg(
        compact!.tBoxDeviceId(), null, null, false, null, Constant.deviceTBox);
  }

  LorinMessage genTBoxUserInfo() {
    return genSpecialOne2OneReadMsg(
        compact!.tBoxUserInfo(), null, null, false, null, Constant.deviceTBox);
  }

  LorinMessage genRebootTBox(int mode) {
    return genSpecialOne2OneWriteMsg(
        compact!.rebootTBoxCmd(),
        Uint8ClampedList.fromList([01, 00, mode]),
        null,
        false,
        null,
        Constant.deviceTBox);
  }

  // LorinMessage genStartUpgradingFirmwareMsg(Uint8ClampedList? para) {
  //   return genSpecialOne2OneWriteMsg(compact!.startUpgradingFirmware(), para,
  //       null, false, null, Constant.deviceScreen);
  // }
  //
  // LorinMessage genStartTransferFirmwareMsg(Uint8ClampedList? para) {
  //   return genSpecialOne2OneWriteMsg(compact!.startTransferFirmware(), para,
  //       null, false, null, Constant.deviceScreen);
  // }

  LorinMessage genSyncRTCMsg(DateTime dateTime) {
    return genSpecialOne2OneWriteMsg(
        compact!.rtcCmd(), Datetime.fromDateTime(dateTime).toBytes());
  }

  LorinMessage genRequestBatteryRealTimeInfoMsg() {
    return genSpecialOne2OneReadMsg(compact!.batteryRealTimeInfoCmd());
  }

  LorinMessage genTransportationModeOnOffMsg(bool on) {
    return genSpecialOne2OneWriteMsg(
        compact!.transportationModeCmd(), ByteUtil.bool2Bytes(on));
  }

  LorinMessage genSpinKillOnOffMsg(bool on) {
    return genSpecialOne2OneWriteMsg(
        compact!.spinKillCmd(), ByteUtil.bool2Bytes(on));
  }

  LorinMessage genSpeedingBrakingOnOffMsg(bool on) {
    return genSpecialOne2OneWriteMsg(
        compact!.speedingBrakingCmd(), ByteUtil.bool2Bytes(on));
  }

  LorinMessage genSoundWaveOnOffMsg(bool on) {
    return genSpecialOne2OneWriteMsg(
        compact!.soundWaveCmd(), ByteUtil.bool2Bytes(on));
  }

  LorinMessage genSoundPackOnOffMsg(bool on) {
    return genSpecialOne2OneWriteMsg(
        compact!.soundPackCmd(), ByteUtil.bool2Bytes(on));
  }

  LorinMessage genSetVolumeMsg(int volume) {
    return genSpecialOne2OneWriteMsg(
        compact!.volumeCmd(), ByteUtil.num2BytesLe(volume, 1));
  }

  LorinMessage genSetStandbyTimeMsg(int seconds) {
    return genSpecialOne2OneWriteMsg(
        compact!.standbyTimeCmd(), ByteUtil.num2BytesLe(seconds, 2));
  }

  LorinMessage genSetSpeedingBrakingSensitivityMsg(int speeding, int braking) {
    return genSpecialOne2OneWriteMsg(
        compact!.speedingBrakingSensitivityCmd(),
        ByteUtil.buildBytes(ByteUtil.num2BytesLe(speeding, 1),
            ByteUtil.num2BytesLe(braking, 1)));
  }

  ///
  /// [type0] 陀螺仪零点校准
  /// [type1] 俯仰角零点校准
  /// [type2] 翻滚角零点校准
  LorinMessage genCalibrateIMUMsg(int type0, int type1, int type2) {
    return genSpecialOne2OneWriteMsg(
        compact!.calibrateImuCmd(), ByteUtil.buildByte(type0, type1, type2));
  }

  /// 查询IMU校准结果
  LorinMessage genQueryIMUCalibrationMsg() {
    return genSpecialOne2OneReadMsg(compact!.calibrateImuCmd());
  }

  LorinMessage genLoadDetectOnOffMsg(bool on) {
    return genSpecialOne2OneWriteMsg(
        compact!.loadDetectCmd(), ByteUtil.bool2Bytes(on));
  }

  LorinMessage genNoLoadDetectOnOffMsg(bool on) {
    return genSpecialOne2OneWriteMsg(
        compact!.noLoadDetectCmd(), ByteUtil.bool2Bytes(on));
  }

  LorinMessage genLowBatteryProtectionModeOnOffMsg(bool on) {
    return genSpecialOne2OneWriteMsg(
        compact!.lowBatteryProtectionModeCmd(), ByteUtil.bool2Bytes(on));
  }

  LorinMessage genTboxLowBatLevelWakeUpVehicleModeOnOffMsg(bool on) {
    return genSpecialOne2OneWriteMsg(
        compact!.lowBatteryWakeUpVehicleModeCmd(), ByteUtil.bool2Bytes(on));
  }

  LorinMessage genShowTboxInfoOnVehicleOnOffMsg(bool on) {
    return genSpecialOne2OneWriteMsg(
        compact!.showTboxInfoCmd(), ByteUtil.bool2Bytes(on));
  }

  LorinMessage genRemainderRangeEstimateOnOffMsg(bool on) {
    return genSpecialOne2OneWriteMsg(
        compact!.remainderRangeEstimateCmd(), ByteUtil.bool2Bytes(on));
  }

  LorinMessage genAutoHeadlightOnOffMsg(bool on) {
    return genSpecialOne2OneWriteMsg(
        compact!.autoHeadlightCmd(), ByteUtil.bool2Bytes(on));
  }

  LorinMessage genSetAutoHeadlightBrightnessThrMsg(int lowThr, int highThr) {
    return genSpecialOne2OneWriteMsg(compact!.autoHeadlightBrightnessThrCmd(),
        ByteUtil.buildByte(lowThr, highThr));
  }

  LorinMessage genSetHeadlightBrightnessMsg(
      {int? brightness, int? lowBeamBrightness, int? highBeamBrightness}) {
    if (brightness != null)
      return genSpecialOne2OneWriteMsg(compact!.brightnessOfHeadlightCmd(),
          ByteUtil.num2BytesLe(brightness, 1));
    if (lowBeamBrightness == null || highBeamBrightness == null) {
      throw InvalidParamException(
          'Both param [lowBeamBrightness] and [highBeamBrightness] could not be null when [on] is null.');
    }
    return genSpecialOne2OneWriteMsg(compact!.brightnessOfHeadlightCmd(),
        ByteUtil.buildByte(lowBeamBrightness, highBeamBrightness));
  }

  LorinMessage genSetDriveModeMsg(int driveMode) {
    return genSpecialOne2OneWriteMsg(
        compact!.driveModeCmd(), ByteUtil.num2BytesLe(driveMode, 1));
  }

  LorinMessage genSetPedalSensitivityMsg(int sensitivity1, int sensitivity2) {
    return genSpecialOne2OneWriteMsg(
        compact!.pedalSensitivityCmd(),
        ByteUtil.buildBytes(ByteUtil.num2BytesLe(sensitivity1, 1),
            ByteUtil.num2BytesLe(sensitivity2, 1)));
  }

  LorinMessage genSetPitchAngleMsg(int angle) {
    return genSpecialOne2OneWriteMsg(
        compact!.pitchAngleCmd(), ByteUtil.num2BytesLe(angle, 2));
  }

  LorinMessage genSetSoundPackIdMsg(int id) {
    return genSpecialOne2OneWriteMsg(
        compact!.soundPackIdCmd(), ByteUtil.num2BytesLe(id, 4));
  }

  LorinMessage genSetSoundWaveSensitivityMsg(int sensitivity) {
    return genSpecialOne2OneWriteMsg(compact!.soundWaveSensitivityCmd(),
        ByteUtil.num2BytesLe(sensitivity, 1));
  }

  LorinMessage genUsbPowerOnOffMsg(bool on) {
    return genSpecialOne2OneWriteMsg(
        compact!.usbPowerCmd(), ByteUtil.bool2Bytes(on));
  }

  LorinMessage genBermAngleModeOnOffMsg(bool on) {
    return genSpecialOne2OneWriteMsg(
        compact!.bermAngleModeCmd(), ByteUtil.bool2Bytes(on));
  }

  LorinMessage genSetLightEffectIdMsg(int id) {
    return genSpecialOne2OneWriteMsg(
        compact!.lightEffectIdCmd(), ByteUtil.num2BytesLe(id, 4));
  }

  @override
  LorinMessage genSetLightEffectModeMsg(int mode,
      [Uint8ClampedList? param, int? source, int? target]) {
    return genSpecialOne2OneWriteMsg(
        compact!.lightEffectModeCmd(), ByteUtil.num2BytesLe(mode, 1));
  }

  LorinMessage genPlaySoundItemMsg(int index) {
    return genSpecialOne2OneWriteMsg(
        compact!.playSoundItemCmd(), ByteUtil.buildByte(index, 1));
  }

  LorinMessage genAssistBalanceOnOffMsg(bool on) {
    return genSpecialOne2OneWriteMsg(
        compact!.assistBalanceCmd(), ByteUtil.bool2Bytes(on));
  }

  LorinMessage genStartMotorAutoCalibrationMsg(
      int hallOffsetCalibrate, int hallSectorCalibrate) {
    return genSpecialMany2ManyWriteMsg(null, Constant.deviceEUCV11Driver, 0x12,
        ByteUtil.buildByte(hallOffsetCalibrate, hallSectorCalibrate));
  }

  LorinMessage genQueryMotorAutoCalibrationResultMsg() {
    return genSpecialMany2ManyReadMsg(null, Constant.deviceEUCV11Driver, 0x12);
  }

  LorinMessage genResetMotorAutoCalibrationEffectMsg(
      {int hallOffset = 1, int hallSector = 1}) {
    return genSpecialMany2ManyWriteMsg(null, Constant.deviceEUCV11Driver, 0x13,
        ByteUtil.buildByte(hallOffset, hallSector));
  }

  LorinMessage genStopMotorAutoCalibrationMsg() {
    return genSpecialMany2ManyWriteMsg(null, Constant.deviceEUCV11Driver, 0x15);
  }

  LorinMessage genStartMotorSelfCheckMsg({int method = 1}) {
    return genSpecialMany2ManyWriteMsg(
        null, Constant.deviceEUCV11Driver, 0x14, ByteUtil.buildByte(method));
  }

  LorinMessage genQueryMotorSelfCheckResultMsg() {
    return genSpecialMany2ManyReadMsg(null, Constant.deviceEUCV11Driver, 0x14);
  }

  LorinMessage genStartBatteryCalibrationMsg() {
    return genSpecialMany2ManyWriteMsg(null, Constant.deviceEUCV11Driver, 0x16);
  }

  LorinMessage genQueryBatteryCalibrationResultMsg() {
    return genSpecialMany2ManyReadMsg(null, Constant.deviceEUCV11Driver, 0x16);
  }

  LorinMessage genSetDeviceNameMsg(String name) {
    return genSpecialMany2ManyWriteMsg(null, Constant.deviceEUCV12BLE,
        compact!.deviceNameCmd(), ByteUtil.str2Bytes(name, true));
  }

  LorinMessage genRequestDeviceNameMsg() {
    return genSpecialMany2ManyReadMsg(
        null, Constant.deviceEUCV12BLE, compact!.deviceNameCmd());
  }

  LorinMessage genSetPasswordMsg(int type, String pwd) {
    return genSpecialMany2ManyWriteMsg(
        null,
        Constant.deviceEUCV12BLE,
        compact!.passwordCmd(),
        ByteUtil.buildBytes(
            ByteUtil.num2BytesLe(type, 1),
            ByteUtil.num2BytesLe(pwd.length, 1),
            ByteUtil.str2Bytes(pwd, false)));
  }

  LorinMessage genSetPasswordTypeMsg(int type) {
    return genSpecialMany2ManyWriteMsg(null, Constant.deviceEUCV12BLE,
        compact!.passwordTypeCmd(), ByteUtil.num2BytesLe(type, 1));
  }

  LorinMessage genRequestPasswordTypeMsg() {
    return genSpecialMany2ManyReadMsg(
        null, Constant.deviceEUCV12BLE, compact!.passwordTypeCmd());
  }
}

abstract class EucCmdCompact extends CmdCompact {
  int batteryRealTimeInfoCmd() {
    return 5;
  }

  @override
  int speedLimitCmd() {
    return 33;
  }

  @override
  int ridingModeCmd() {
    return 36;
  }

  @override
  int lockCmd() {
    return 49;
  }

  int transportationModeCmd() {
    return 50;
  }

  int spinKillCmd() {
    return 46;
  }

  @override
  int settingsCmd() {
    return 32;
  }

  int playSoundItemCmd() {
    return 65;
  }

  int volumeCmd() {
    return 38;
  }

  int standbyTimeCmd() {
    return 40;
  }

  int soundPackCmd() {
    return 44;
  }

  int speedingBrakingCmd() {
    return 62;
  }

  int speedingBrakingSensitivityCmd() {
    return 63;
  }

  int calibrateImuCmd() {
    return 82;
  }

  int loadDetectCmd() {
    return 53;
  }

  int noLoadDetectCmd() {
    return 54;
  }

  int driveModeCmd() {
    return 35;
  }

  int pedalSensitivityCmd() {
    return 37;
  }

  int pitchAngleCmd() {
    return 34;
  }

  int soundPackIdCmd() {
    return 39;
  }

  int rtcCmd() {
    return 52;
  }

  int lowBatteryProtectionModeCmd() {
    return 55;
  }

  int lowBatteryWakeUpVehicleModeCmd() {
    return 71;
  }

  int showTboxInfoCmd() {
    return 72;
  }

  int assistBalanceCmd() {
    return 64;
  }

  int deviceNameCmd();

  int passwordCmd();

  int passwordTypeCmd();

  int autoHeadlightCmd();

  int autoHeadlightBrightnessThrCmd();

  int brightnessOfHeadlightCmd();

  int remainderRangeEstimateCmd();

  int usbPowerCmd();

  int soundWaveCmd();

  int soundWaveSensitivityCmd();

  int lightEffectIdCmd();

  int lightEffectModeCmd();

  @override
  int safeSpeedLimitCmd() => 0;

  int bermAngleModeCmd();
}
